package org.iwidget.desktop.ui;
import org.iwidget.desktop.core.Iwidget;
import org.iwidget.desktop.model.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
/**
 *
 * @author Muhammad Hakim A
 */


public class PreferenceFrame extends JDialog
    implements ActionListener, WindowListener
{
    class MyButton extends JButton
    {

        private static final long serialVersionUID = 0x3737393639363031L;
        JTextField field;

        public MyButton(JTextField field, String string)
        {
            super(string);
            this.field = field;
        }
    }

    class MyFilter extends FileFilter
    {

        public boolean accept(File file)
        {
            return file.getName().endsWith(fileType);
        }

        public String getDescription()
        {
            return "*" + fileType;
        }

        String fileType;

        public MyFilter(String fileType)
        {
            this.fileType = fileType;
        }
    }


    public PreferenceFrame(WidgetElement widget)
    {
        super(widget.getParent());
        this.widget = widget;
        componentList = new ArrayList();
        setTitle(widget.getWindowJS().getTitle());
        setSize(350, calculateHeight() + 95);
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        int x = widget.getWindowJS().getX();
        if(x < 0)
            x = 0;
        if(x + 350 > screen.width)
            x = screen.width - 350;
        int y = widget.getWindowJS().getY() + widget.getWindowJS().getHeight();
        if(y < 0)
            y = 0;
        if(y + widget.getPreferenceObjects().size() * 40 + 120 > screen.height)
            y = widget.getWindowJS().getY() - (widget.getPreferenceObjects().size() * 40 + 100);
        getContentPane().setLayout(new BorderLayout());
        buildPreferencePanel();
        JPanel p = new JPanel();
        getContentPane().add(p, "South");
        JButton saveButton = new JButton("Save");
        saveButton.addActionListener(this);
        p.add(saveButton);
        JButton cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(this);
        p.add(cancelButton);
        widget.triggerEvent("onMayChangePreferences");
        addWindowListener(this);
        setLocation(x, y);
        setModal(true);
        setVisible(true);
    }

    private int calculateHeight()
    {
        int height = 0;
        for(int iCtr = 0; iCtr < widget.getPreferenceObjects().size(); iCtr++)
        {
            ElementPreferences pref = (ElementPreferences)widget.getPreferenceObjects().get(iCtr);
            if(!pref.getVisible())
                continue;
            String type = pref.getType();
            if(type.equals("slider"))
            {
                height += 85;
                continue;
            }
            if(type.equals("list"))
                height += 18 * pref.getLines();
            else
                height += 25;
        }

        return height;
    }

    private void buildPreferencePanel()
    {
        errorLabel = new JLabel();
        errorLabel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        getContentPane().add(errorLabel, "Center");
        ArrayList tabPanels = new ArrayList();
        JPanel lonePanel = new JPanel();
        lonePanel.setLayout(new BoxLayout(lonePanel, 1));
        lonePanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        tabPanels.add(lonePanel);
        JTabbedPane tabbedPane = null;
        for(int iCtr = 0; iCtr < widget.getPreferenceObjects().size(); iCtr++)
        {
            int addTab = 0;
            ElementPreferences pref = (ElementPreferences)widget.getPreferenceObjects().get(iCtr);
            if(!pref.getVisible())
                continue;
            JPanel itemPanel = new JPanel(new BorderLayout());
            itemPanel.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0));
            JLabel label = new JLabel(pref.getTitle());
            itemPanel.add(label, "West");
            label.setPreferredSize(new Dimension(100, 20));
            String value = pref.getValue();
            if(value == null)
                value = pref.getDefaultValue();
            String type = pref.getType();
            if(tabbedPane == null && type.equals("tabpane"))
            {
                tabPanels.remove(0);
                tabbedPane = new JTabbedPane();
                tabbedPane.setPreferredSize(new Dimension(getWidth(), getHeight() - 95));
                ArrayList tabs = pref.getTabsArray();
                for(int jCtr = 0; jCtr < tabs.size(); jCtr++)
                {
                    String tab = (String)tabs.get(jCtr);
                    JPanel inset = new JPanel(new BorderLayout());
                    JPanel innerPanel = new JPanel();
                    innerPanel.setLayout(new BoxLayout(innerPanel, 1));
                    innerPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
                    inset.add(innerPanel, "North");
                    tabbedPane.addTab(tab, inset);
                    tabPanels.add(innerPanel);
                    addTab = -1;
                }

                componentList.add(tabbedPane);
            } else
            if(type.equals("checkbox"))
            {
                JCheckBox check = new JCheckBox();
                check.setToolTipText(pref.getDescription());
                if(value.equals("true"))
                    check.setSelected(true);
                else
                    check.setSelected(false);
                componentList.add(check);
                itemPanel.add(check, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("spinner"))
            {
                if(value.length() == 0)
                    value = "0";
                SpinnerNumberModel model = new SpinnerNumberModel(Integer.parseInt(value), pref.getMinLength(), pref.getMaxLength(), 1);
                JSpinner spinner = new JSpinner(model);
                spinner.setToolTipText(pref.getDescription());
                componentList.add(model);
                itemPanel.add(spinner, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("dateSpinner"))
            {
                SpinnerDateModel model = new SpinnerDateModel();
                JSpinner spinner = new JSpinner(model);
                spinner.setToolTipText(pref.getDescription());
                Calendar calendar = new GregorianCalendar();
                if(value.length() > 0)
                    calendar.setTimeInMillis(Long.parseLong(value));
                spinner.setValue(calendar.getTime());
                componentList.add(model);
                itemPanel.add(spinner, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("text"))
            {
                JTextField field = new JTextField(value);
                field.setToolTipText(pref.getDescription());
                componentList.add(field);
                itemPanel.add(field, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("password"))
            {
                JPasswordField field = new JPasswordField(value);
                field.setToolTipText(pref.getDescription());
                componentList.add(field);
                itemPanel.add(field, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("popup"))
            {
                JComboBox combo = new JComboBox();
                combo.setToolTipText(pref.getDescription());
                int selection = 0;
                ArrayList options = pref.getOptionsArray();
                for(int jCtr = 0; jCtr < options.size(); jCtr++)
                {
                    combo.addItem(options.get(jCtr));
                    if(value.equals(options.get(jCtr)))
                        selection = jCtr;
                }

                combo.setToolTipText(pref.getDescription());
                combo.setSelectedIndex(selection);
                componentList.add(combo);
                itemPanel.add(combo, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("list"))
            {
                JList list = new JList();
                list.setToolTipText(pref.getDescription());
                list.setSelectionMode(0);
                if(pref.getSelect().equals("multiple"))
                    list.setSelectionMode(2);
                JScrollPane scroller = new JScrollPane();
                scroller.setBackground(new Color(0, 0, 0, 0));
                scroller.getViewport().add(list);
                scroller.setAutoscrolls(true);
                scroller.setPreferredSize(new Dimension(100, 18 * pref.getLines()));
                ArrayList options = pref.getOptionsArray();
                StringTokenizer tokens = new StringTokenizer(value, ",");
                String listData[] = new String[options.size()];
                int selection[] = new int[tokens.countTokens()];
                int selCtr = 0;
                for(int jCtr = 0; jCtr < options.size(); jCtr++)
                {
                    listData[jCtr] = (String)options.get(jCtr);
                    String option = (String)options.get(jCtr);
                    if(value.indexOf(option + ",") > -1 || value.indexOf("," + option) > -1 || value.equals(option))
                        selection[selCtr++] = jCtr;
                }

                list.setListData(listData);
                list.clearSelection();
                list.setSelectedIndices(selection);
                componentList.add(list);
                itemPanel.add(scroller, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("slider"))
            {
                if(value == null || value.length() == 0)
                    value = "0";
                JSlider slider = new JSlider();
                slider.setToolTipText(pref.getDescription());
                slider.setMaximum(pref.getMaxLength());
                slider.setMinimum(pref.getMinLength());
                slider.setMajorTickSpacing(280 / pref.getTicks());
                slider.setValue(Integer.parseInt(value));
                slider.setPaintTicks(true);
                ArrayList tickLabels = pref.getTickLabels();
                if(tickLabels.size() > 0)
                {
                    int offset = 255 / tickLabels.size();
                    if(tickLabels.size() > 1)
                        offset = 255 / (tickLabels.size() - 1);
                    Hashtable labels = new Hashtable();
                    for(int jCtr = 0; jCtr < tickLabels.size(); jCtr++)
                        labels.put(new Integer(jCtr * offset), new JLabel((String)tickLabels.get(jCtr), 0));

                    slider.setLabelTable(labels);
                    slider.setPaintLabels(true);
                }
                componentList.add(slider);
                itemPanel.add(slider, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            } else
            if(type.equals("selector"))
            {
                JPanel p3 = new JPanel();
                p3.setLayout(new BorderLayout());
                JTextField field = new JTextField(pref.getValue());
                field.setToolTipText(pref.getDescription());
                MyButton button = new MyButton(field, "Browse...");
                button.add("field", field);
                button.setActionCommand("browse:" + iCtr);
                button.addActionListener(this);
                p3.add(field, "Center");
                p3.add(button, "East");
                componentList.add(field);
                itemPanel.add(p3, "Center");
                addTab = getTab(tabbedPane, pref.getTabName());
            }
            if(addTab > -1)
            {
                JPanel boxPanel = (JPanel)tabPanels.get(addTab);
                boxPanel.add(itemPanel);
            }
        }

        if(tabbedPane != null)
        {
            getContentPane().add(tabbedPane, "North");
        } else
        {
            JPanel boxPanel = (JPanel)tabPanels.get(0);
            getContentPane().add(boxPanel, "North");
        }
    }

    private int getTab(JTabbedPane tabbedPane, String tabName)
    {
        int addTab = 0;
        if(tabbedPane != null && tabName != null)
        {
            for(int jCtr = 0; addTab == 0 && jCtr < tabbedPane.getTabCount(); jCtr++)
                if(tabbedPane.getTitleAt(jCtr).equals(tabName))
                    addTab = jCtr;

        }
        return addTab;
    }

    private boolean isValid(ElementPreferences pref, String value)
    {
        boolean isValid = true;
        if(pref.getValidator() != null)
            try
            {
                String args[] = new String[1];
                args[0] = value;
                if(widget.executeJavaScriptFunction(pref.getValidator(), args) == null)
                    isValid = false;
            }
            catch(Exception ex)
            {
                isValid = false;
            }
        return isValid;
    }

    public void actionPerformed(ActionEvent e)
    {
        if(e.getActionCommand().equals("Save"))
        {
            boolean canClose = true;
            int offset = 0;
            for(int iCtr = 0; iCtr < widget.getPreferenceObjects().size(); iCtr++)
            {
                ElementPreferences pref = (ElementPreferences)widget.getPreferenceObjects().get(iCtr);
                if(!pref.getVisible())
                    continue;
                String type = pref.getType();
                if(type.equals("checkbox"))
                {
                    JCheckBox check = (JCheckBox)componentList.get(offset);
                    pref.setValue("" + check.isSelected());
                } else
                if(type.equals("spinner"))
                {
                    SpinnerNumberModel model = (SpinnerNumberModel)componentList.get(offset);
                    pref.setValue("" + model.getNumber().intValue());
                } else
                if(type.equals("dateSpinner"))
                {
                    SpinnerDateModel model = (SpinnerDateModel)componentList.get(offset);
                    pref.setValue("" + model.getDate().getTime());
                } else
                if(type.equals("text"))
                {
                    JTextField field = (JTextField)componentList.get(offset);
                    if(isValid(pref, field.getText()))
                    {
                        String fieldValue = Iwidget.replace(field.getText(), "\\", "/", 0);
                        pref.setValue(fieldValue);
                    } else
                    {
                        errorLabel.setText(pref.getValidatorMessage());
                        canClose = false;
                    }
                } else
                if(type.equals("password"))
                {
                    JComponent c = (JComponent)componentList.get(offset);
                    JPasswordField field = (JPasswordField)componentList.get(offset);
                    String password = new String(field.getPassword());
                    if(isValid(pref, password))
                    {
                        pref.setValue(password);
                    } else
                    {
                        errorLabel.setText(pref.getValidatorMessage());
                        canClose = false;
                    }
                } else
                if(type.equals("list"))
                {
                    JList list = (JList)componentList.get(offset);
                    int selects[] = list.getSelectedIndices();
                    ArrayList options = pref.getOptionsArray();
                    String value = "";
                    for(int jCtr = 0; jCtr < selects.length; jCtr++)
                    {
                        if(value.length() > 0)
                            value = value + ",";
                        value = value + (String)options.get(selects[jCtr]);
                    }

                    pref.setValue(value);
                } else
                if(type.equals("popup"))
                {
                    JComboBox combo = (JComboBox)componentList.get(offset);
                    ArrayList options = pref.getOptionsArray();
                    pref.setValue((String)options.get(combo.getSelectedIndex()));
                } else
                if(type.equals("slider"))
                {
                    JSlider slider = (JSlider)componentList.get(offset);
                    pref.setValue("" + slider.getValue());
                } else
                if(type.equals("selector"))
                {
                    JTextField field = (JTextField)componentList.get(offset);
                    if(isValid(pref, field.getText()))
                    {
                        pref.setValue(field.getText());
                    } else
                    {
                        errorLabel.setText(pref.getValidatorMessage());
                        canClose = false;
                    }
                }
                offset++;
            }

            if(canClose)
            {
                dispose();
                widget.triggerEvent("onPreferencesChanged");
            }
        } else
        if(e.getActionCommand().equals("Cancel"))
        {
            dispose();
            errorLabel = null;
            componentList = null;
            widget = null;
            System.gc();
        } else
        if(e.getActionCommand().startsWith("browse:"))
        {
            MyButton button = (MyButton)e.getSource();
            int value = Integer.parseInt(e.getActionCommand().substring(7));
            ElementPreferences pref = (ElementPreferences)widget.getPreferenceObjects().get(value);
            JFileChooser chooser = new JFileChooser(pref.getDirectory());
            try
            {
                chooser.setSelectedFile(new File((new File(pref.getFile())).getCanonicalPath()));
            }
            catch(Exception ex) { }
            for(int iCtr = 0; iCtr < pref.getExtensions().size(); iCtr++)
                chooser.addChoosableFileFilter(new MyFilter((String)pref.getExtensions().get(iCtr)));

            if(pref.getKind().equals("files"))
                chooser.setFileSelectionMode(0);
            else
            if(pref.getKind().equals("folders"))
                chooser.setFileSelectionMode(1);
            else
                chooser.setFileSelectionMode(2);
            int returnVal = 0;
            if(pref.getStyle().equals("open"))
                returnVal = chooser.showOpenDialog(this);
            else
                returnVal = chooser.showSaveDialog(this);
            if(returnVal == 0)
            {
                pref.setValue(chooser.getSelectedFile().getAbsolutePath());
                button.field.setText(chooser.getSelectedFile().getAbsolutePath());
            }
        }
    }

    public void windowClosing(WindowEvent e)
    {
        dispose();
        errorLabel = null;
        componentList = null;
        widget = null;
        System.gc();
    }

    public void windowDeactivated(WindowEvent windowevent)
    {
    }

    public void windowActivated(WindowEvent windowevent)
    {
    }

    public void windowDeiconified(WindowEvent windowevent)
    {
    }

    public void windowIconified(WindowEvent windowevent)
    {
    }

    public void windowOpened(WindowEvent windowevent)
    {
    }

    public void windowClosed(WindowEvent windowevent)
    {
    }

    private static final long serialVersionUID = 0x3836343639353431L;
    private WidgetElement widget;
    private ArrayList componentList;
    private JLabel errorLabel;
}